﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using PluginInterface;
using System.IO;
using Calculadora;
using System.Windows.Forms;


namespace Calculadora
{
    public class Metodos
    {

        //ATRIBUTOS
        private List<Plugin> ListaPlugin = new List<Plugin>();

        //CONSTRUCTOR
        public Metodos() { }

        //METODOS

        /// <summary>
        /// Encuentra un archivos con extencion "dll" dando una direccion 
        /// </summary>
        /// <param name="camino"></param> direccion en donde se encuentran los "dll"
        private void encontrarPlugins(String camino) {
            ListaPlugin.Clear();  //limpiamos la lista de plugins
            //obtengo los nombre de los archivos que se encuentran en el directorio indicado
            String[] archivos = Directory.GetFiles(camino);
            //si los archivos son dll entonces los agrego
            foreach (String arch in archivos) {
                FileInfo file = new FileInfo(arch);
                if (file.Extension.Equals(".dll"))
                {
                    this.agregarPlugin(arch);
                }
            }
            
        }

        /// <summary>
        /// Proporciona una lista que contiene plugins
        /// </summary>
        /// <returns></returns>
        public List<Plugin> getListaPlugins() { return ListaPlugin; }

        /// <summary>
        /// Agrega los plugin a una lista previamente instanciandolos
        /// </summary>
        /// <param name="InfoPlugin"></param>
        private void agregarPlugin(String InfoPlugin) {
            //cargo un assembly con el archivo
            Assembly pluginAssembly = Assembly.LoadFrom(InfoPlugin);
            //controlo los tipos de de los assembly
            foreach (Type tipo in pluginAssembly.GetTypes()) {
                if (tipo.IsPublic)
                {
                    if (!tipo.IsAbstract)  
                    {
                        Type tipoInterface = tipo.GetInterface("PluginInterface.Plugin", true);
                        if (tipoInterface != null)
                        {
                            // creo y agrego a la lista las instancias de los plugins
                             ListaPlugin.Add((Plugin)Activator.CreateInstance(pluginAssembly.GetType(tipo.ToString())));                   
                        }

                        tipoInterface = null; 			
                    }
                }
            }


            pluginAssembly = null;
        
        }
        /// <summary>
        /// Carga los plugins al sistema
        /// </summary>

        public void cargarPlugins() {
            // le doy la direccion donde se va a cargar la aplicacion
            this.encontrarPlugins(Application.StartupPath + @"\Plugins");        
        }

        /// <summary>
        /// busca un plugin con el mismo nombre que se pasa por paramtro
        /// retorna null si no se encuentra en la lista de Plugins
        /// </summary>
        /// <param name="a"></param> nombre del plugin que se quiere encontrar
        /// <returns></returns> plugin encontrado, retorna null si no encuentra el Plugin 
        /// con el nombre especificado
        public Plugin encontrarPluginPorNombre(string a){
            Plugin PluginEncontrado  = null;
            foreach (Plugin p in ListaPlugin)
            {
                if (p.Nombre.Equals(a))
                {
                    PluginEncontrado = p;
                }
            }
            return PluginEncontrado;
        }

        /// <summary>
        /// 
        /// Retorna el resultado de la operacion entre dos operandos
        /// </summary>
        /// <param name="a"></param> Representa un operando
        /// <param name="b"></param>Representa un operando
        /// <param name="operador"></param>es el nombre del operador que se desea usar y buscar
        /// <returns></returns>Resultado en String de la operacion 
        public string resultadoPlugin(string a, string b, string operador) {
            Plugin p = encontrarPluginPorNombre(operador);
            if (p == null) { return ("No se encontró el plugin."); }
            else {
                try
                {
                    double op1 = Convert.ToDouble(a);
                    double op2 = Convert.ToDouble(b);
                    if (!p.control(op1,op2).habilitado())
                    {
                        return p.control(op1, op2).informe();
                    }
                    else { return ("Resultado : " + p.operacion(op1, op2)); }
                }
                catch (FormatException) { return ("Argumentos no válidos."); }    
            }
        }
  
    
    }
}
